package com.basic.common.advisor;


import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.basic.common.annotation.DictParam;
import com.basic.common.utils.PageUtils;
import com.basic.common.utils.R;
import com.basic.config.DictConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

@Slf4j
@ControllerAdvice
public class ResponseAdvisor implements ResponseBodyAdvice<Object> {

    public static final String GET = "get";

    public static final String SET = "set";

//    private static int count = 0;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        resolveByRecursion(body);
        return body;
    }

    private void resolveByRecursion(Object body) {
        if (body instanceof R) {
            R r = (R) body;
            int code = (int) r.get("code");
            if (code == 0) {
                Object data = r.get("data");
                if (data != null) {
                    if (data instanceof PageUtils) {
                        List<?> list = ((PageUtils) data).getList();
                        for (Object o : list) {
                            resolve(o);
                        }
                    } else if (data instanceof List) {
                        for (Object o : ((List) data)) {
                            resolve(o);
                        }
                    } else {
                        resolve(data);
                    }
                }
            }
        }
    }

    private void resolve(Object object) {
//        count++;
        if (object != null) {
            Field[] fields = ReflectUtil.getFields(object.getClass());
            for (Field field : fields) {
                field.setAccessible(true); // 如果是private时，意为允许访问该字段
                Class<?> fieldType = field.getType(); // 获取该字段的类型

                // 只处理string类型
                if (fieldType == String.class) {
                    DictParam dictParam = AnnotationUtil.getAnnotation(field, DictParam.class);
                    if (dictParam != null) {
                        if (StrUtil.isNotBlank(dictParam.field())
                                && StrUtil.isNotBlank(dictParam.targetField())
                                && StrUtil.isNotBlank(dictParam.dictType())) {
                            String oldDictType = dictParam.dictType();
                            String oldField = dictParam.field();
                            String oldTargetField = dictParam.targetField();
                            // 字典转换开始（使用反射）
                            Class<?> clazz = object.getClass();
                            try {
                                // 反射调用get方法获取字段值
                                Method sourceMethod = clazz.getMethod(GET + firstToUppercase(oldField));
                                Object fieldValue = sourceMethod.invoke(object);
                                if (ObjectUtil.isNull(fieldValue)) {
                                    ReflectUtil.setFieldValue(object, oldTargetField, "");
                                }
                                // 获取字典值
                                Map<String, String> dictVoMap = DictConfig.DICT_MAPPER.get(oldDictType);
                                if (dictVoMap.isEmpty()) {
                                    ReflectUtil.setFieldValue(object, oldTargetField, "");
                                } else {
                                    String dictName = dictVoMap.get(fieldValue.toString());
                                    ReflectUtil.setFieldValue(object, oldTargetField, dictName);
                                }
                            } catch (Throwable throwable) {
                                log.error("error:", throwable);
                            }
                        }
                    }
                } else if (fieldType == List.class) {
                    Object value = ReflectUtil.getFieldValue(object, field);
                    if (ObjectUtil.isNotEmpty(value)) {
                        for (Object o : ((List) value)) {
//                            if (count < 10000) {
//                                resolve(o);
//                            }
                            resolve(o);
                        }
                    }
                }
//                else {
//                    Object value = ReflectUtil.getFieldValue(object, field);
//                    if (ObjectUtil.isNotEmpty(value)) {
//                        if (count < 10000) {
//                            resolve(value);
//                        }
//                    }
//                }
            }
        }
    }

    private String firstToUppercase(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
}
